package com.avo.ramcache.orm.impl.m2s;

import com.avo.ramcache.orm.impl.HibernateQuerier;
import org.hibernate.*;
import org.springframework.orm.hibernate5.HibernateCallback;

import java.util.List;

public class M2SHibernateQuerier extends HibernateQuerier {

    public M2SHibernateQuerier() {
    }

    public M2SHibernateQuerier(SessionFactory sessionFactory) {
        super(sessionFactory);
    }

    @Override
    public <T> List<T> all(Class<T> clz) {
        // todo 遍历所有server 合并result
        return super.all(clz);
    }

    @Override
    public <T> List<T> listAll(Class<T> clz, String queryname, Object... params) {
        // todo 遍历所有server 合并result
        return super.listAll(clz, queryname, params);
    }

    @Override
    public <T> List<T> allByServer(int server, Class<T> clz) {
        ServerHibernateTemplate hibernateTemplate = (ServerHibernateTemplate) getHibernateTemplate();
        return hibernateTemplate.allByServer(server, clz);
    }

    @Override
    public <T> List<T> listCommon(Class<T> clz, String queryname, Object... params) {
        return super.listCommon(clz, queryname, params);
    }

    @Override
    public <T> List<T> listByServer(int server, Class<T> clz, String queryname, Object[] querynameParams) {
        ServerHibernateTemplate hibernateTemplate = (ServerHibernateTemplate) getHibernateTemplate();
        return hibernateTemplate.M2SListByServer(server, clz, queryname, querynameParams);
    }

    @Override
    public <T> List<T> listByServerWithLimit(int server, int limit, Class<T> clz, String queryname, Object[] querynameParams) {
        ServerHibernateTemplate hibernateTemplate = (ServerHibernateTemplate) getHibernateTemplate();
        return hibernateTemplate.M2SListByTableName(server, 1, limit, clz, queryname, querynameParams);
    }

    @Override
    public <T> T unique(Class<T> clz, String queryname, Object... params) {
        throw new RuntimeException("m2s can not support this method");
    }

    @Override
    public <T> T unique(int server, Class<T> clz, String queryname, Object... params) {
        return getHibernateTemplate().executeWithNativeSession(new HibernateCallback<T>() {
            @Override
            public T doInHibernate(Session session) throws HibernateException {
                Query query = session.getNamedQuery(queryname);
                String tableName = queryname.split("\\.")[0];
                String newTableName = M2SHibernateHelper.tableName(server, tableName);
                String queryString = query.getQueryString();
                String newSql = queryString.replace(tableName, newTableName);
                newSql = "select * " + newSql;
                SQLQuery sqlQuery = session.createSQLQuery(newSql);
                for (int i = 0; i < params.length; i++) {
                    query.setParameter(i, params[i]);
                }
                if (clz != null) {
                    sqlQuery.addEntity(clz);
                }
                return (T) sqlQuery.uniqueResult();
            }
        });
    }

    @Override
    public void executeByServer(int server, String queryname, Object[] params) {
        ServerHibernateTemplate hibernateTemplate = (ServerHibernateTemplate) getHibernateTemplate();
        assert hibernateTemplate != null;
        hibernateTemplate.M2SExecuteByServer(server, queryname, params);
    }

    public int sql(String newSql) {
        ServerHibernateTemplate hibernateTemplate = (ServerHibernateTemplate) getHibernateTemplate();
        return hibernateTemplate.sql(newSql);
    }
}
